package com.vaye.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 用户session工具类
 *
 * @author wangzhiyong
 * @module admin
 * @date 2023年06月30日 下午1:51
 */
@Slf4j
public class UserSessionUtils {

    private final static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private final static ReentrantReadWriteLock.ReadLock readLock = lock.readLock();

    private final static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    // 当前登录用户的id和websocket session的map
    private static ConcurrentHashMap<Long, Session> userSessions = new ConcurrentHashMap<>();

    // 用户昵称map
    private static ConcurrentHashMap<Long, String> userNicks = new ConcurrentHashMap<>();

    // 房间号和用户集合
    private static ConcurrentHashMap<String, List<Long>> roomUsers = new ConcurrentHashMap<>();

    /**
     * 添加用户
     * @author wangzhiyong
     * @date 2023/6/29 上午10:46
     * @param userId
     * @param session
     */
    public static void add(Long userId,Session session,String nickName){
        if (!userSessions.containsKey(userId)) {
            userSessions.put(userId,session);
        }

        if (!userNicks.containsKey(userId)) {
            userNicks.put(userId,nickName);
        }

    }

    /**
     * 移除用户
     * @author wangzhiyong
     * @date 2023/6/29 上午10:47
     * @param userId
     */
    public static void remove(Long userId){
        if (userSessions.containsKey(userId)) {
            userSessions.remove(userId);
        }

        if (userNicks.containsKey(userId)) {
            userNicks.remove(userId);
        }
    }

    /**
     * 获取用户昵称
     * @author wangzhiyong
     * @date 2023/6/30 下午2:11
     * @param userId
     * @return java.lang.String
     */
    public static String getNickName(Long userId){
        return userNicks.get(userId);
    }

    /**
     * 根据用户ID获取用户会话
     * @author wangzhiyong
     * @date 2023/6/30 下午2:13
     * @param userId
     * @return javax.websocket.Session
     */
    public static Session getSession(Long userId){
        return userSessions.get(userId);
    }

    /**
     * 是否有用户会话
     * @author wangzhiyong
     * @date 2023/6/30 下午2:16
     * @return boolean
     */
    public static boolean isEmpty(){
        return userSessions.isEmpty();
    }

    /**
     * 获取所有会话
     * @author wangzhiyong
     * @date 2023/6/30 下午2:47
     * @return java.util.concurrent.ConcurrentHashMap<java.lang.Long,javax.websocket.Session>
     */
    public static ConcurrentHashMap<Long, Session> getUserSessions(){
        return userSessions;
    }

    /**
     * 加入房间
     * @author wangzhiyong
     * @date 2023/6/30 下午3:03
     * @param roomId 房间ID
     * @param userId 用户ID
     */
    public static void addRoom(String roomId,Long userId){
        writeLock.lock();
        try {
            if (roomUsers.containsKey(roomId)) {
                List<Long> list = roomUsers.get(roomId);
                list.add(userId);
                roomUsers.put(roomId, list);
            } else {
                List<Long> objects = new ArrayList<>();
                objects.add(userId);
                roomUsers.put(roomId,objects);
            }
            System.out.println("roomUsers = " + roomUsers.get(roomId));
        } catch (Exception e) {
            log.error("加入房间失败roomId={},userId={}",roomId,userId);
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    /**
     * 退出房间
     * @author wangzhiyong
     * @date 2023/6/30 下午3:05
     * @param roomId
     * @param userId
     */
    public static void exitRoom(String roomId,Long userId){
        writeLock.lock();
        try {
            if (roomUsers.containsKey(roomId)) {
                List<Long> list = roomUsers.get(roomId);
                list.remove(userId);
                roomUsers.put(roomId, list);
            }
            //移除用户相关信息
            remove(userId);
            List<Long> list = roomUsers.get(roomId);
            System.out.println("list = " + list);
        } catch (Exception e) {
            log.error("退出房间失败，roomId={},userId={}",roomId,userId);
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    /**
     * 获取房间所有会话
     * @author wangzhiyong
     * @date 2023/6/30 下午3:13
     * @param roomId
     * @return java.util.List<org.springframework.data.util.Pair<java.lang.Long,javax.websocket.Session>>
     */
    public static List<Pair<Long,Session>> getRoomSessions(String roomId){
        List<Pair<Long,Session>> list = new ArrayList<>();
        readLock.lock();
        try {
            if (!roomUsers.containsKey(roomId)) {
                return list;
            }
            List<Long> userIds = roomUsers.get(roomId);
            if (!CollectionUtils.isEmpty(userIds)) {
                userIds.stream().forEach(e ->{
                    list.add(Pair.of(e,userSessions.get(e)));
                });
            }
        } catch (Exception e) {
            log.error("获取房间用户会话失败");
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }
        return list;
    }
}
